/**
 * Lockbox
 * a Password and Secret Information Manager
 * View to display and edit a single item
 *
 * Created by Nathan Black
 */

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <UIKit/UIApplication.h>
#import <UIKit/UITable.h>
#import <UIKit/UIDatePicker.h>
#import "LockboxItemView.h"
#import "LockboxStorage.h"


@interface LockboxItemView (Private)

- (void)returnFromItemView:(LockboxItem*)item itemDeleted:(BOOL)itemDeleted;
- (void)transToTagView:(NSMutableArray*)tags;
- (void)save;
- (void)reconfig;
- (void)reconfigTags;
- (NSString*)getTextField:(int)fieldIdx;
- (void)deleteItem:(LockboxItem*)item;
- (void)returnToListAndSave:(BOOL)saveOrNot;
- (int)fieldCountForType;

@end

@implementation LockboxItemView

- (void)dealloc
{
    [_navBar release];
    [_prefsTable release];
    [_editCell release];
    int i;
    for (i = 0; i < LBIV_MAXFIELDROWS; i++) {
        [_editField[i] release];
    }

	[super dealloc];
}

///////////// Constructor ////////////////
- (id)initWithFrame:(struct CGRect)frame app:(id)app;
{
    self = [super initWithFrame:frame];
    if (self)
    {
        _transDelegate = app;
        
        _navBar = [[UINavigationBar alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 320.0f, LBIV_NAVBAR_HEIGHT)];
        [_navBar showButtonsWithLeftTitle: @"Done" rightTitle:NULL leftBack: TRUE];
        //[_navBar setPrompt: @"Details"];
        [_navBar setBarStyle: 3];
        [_navBar enableAnimation];
        [_navBar setDelegate: self];

        //CGRect leftButtonRect = [[_navBar->_leftButton _layer] bounds];
        //NSLog(@"left button top: %3.1f height %3.1f", bounds.origin.y, bounds.size.height);

        _typeSegCtl = [[UISegmentedControl alloc] initWithFrame:CGRectMake(80.0f, 8.0f, 230.0f, 30.0f) withStyle:2 withItems:NULL];
        [_typeSegCtl insertSegment:0 withTitle:@"Password" animated:FALSE];
        [_typeSegCtl insertSegment:1 withTitle:@"Card" animated:FALSE];
        [_typeSegCtl insertSegment:2 withTitle:@"Other" animated:FALSE];
        [_typeSegCtl setDelegate:self];
        [_navBar addSubview:_typeSegCtl];
        NSLog(@"navigation items is: %@", [_navBar navigationItems]);

        _editCell = [[UIPreferencesTableCell alloc] init];
        _delGroupCell = [[UIPreferencesTableCell alloc] init];
        _tagGroupCell = [[UIPreferencesTableCell alloc] init];
        [_tagGroupCell setTitle: @"Tags"];
        _tagsCell = [[UIPreferencesTableCell alloc] init];
        [_tagsCell setShowDisclosure:YES];
        
        int i;
        for (i = 0; i < LBIV_MAXFIELDROWS; i++) {
            _editField[i] = [[UIPreferencesTextTableCell alloc] init];
        }
        
        frame.origin.y = LBIV_NAVBAR_HEIGHT;
        frame.size.height -= LBIV_NAVBAR_HEIGHT;
        _prefsTable = [[UIPreferencesTableEx alloc] initWithFrame: frame];
        [_prefsTable setDataSource: self];
        [_prefsTable setDelegate: self];

        [self addSubview: _navBar];
        [self addSubview: _prefsTable];
        
        //UIDatePicker* scrub = [[UIDatePicker alloc] initWithFrame:CGRectMake(10.0f, 100.0f, 300.0f, 150.0f)];
        //[self addSubview: scrub];
    }
    
    return self;
}

- (void)setDeleteDelegate:(id)object
{
    _deleteDelegate = object;
}

- (void)setItem:(LockboxItem*)item
{
    _item = item;
    [_typeSegCtl selectSegment:_item->type];
    [self reconfig];    
}

- (LockboxItem*)item
{
    [self save];
    return _item;
}

- (void)reconfig
{
    /* 
        Keyboard Types:
        0: Standard
        1: Standard but numbers come up first
        2: Phone number pad with +,*,#,"pause" (Modem mode i guess)
        3: URL
        4: lowercase only with dialpad numbers, no punct
        5: Standard w/ alpha
        6: Numberpad only
        7: Numberpad only w/ alpha
        8: email
        9:
    */
    
    switch (_item->type) {
        case LBI_PASSWORD:
            [_editField[0] setTitle: @"Username"];
            [[_editField[0] textField] setText: _item->key];
            [[_editField[0] textField] setAutoCapsType: 0];
            [[_editField[0] textField] setAutoCorrectionType: 1];
            [_editField[1] setTitle: @"Password"];
            [[_editField[1] textField] setText: _item->value];
            [[_editField[1] textField] setAutoCapsType: 0];
            [[_editField[1] textField] setAutoCorrectionType: 1];
            [[_editField[1] textField] setPreferredKeyboardType: 0];
            [_editField[2] setTitle: @"Website"];
            [[_editField[2] textField] setText: _item->website];
            [[_editField[2] textField] setAutoCapsType: 0];
            [[_editField[2] textField] setPreferredKeyboardType: 3];
            [[_editField[2] textField] setAutoCorrectionType: 3];
            [_editField[3] setTitle: @"Note"];
            [[_editField[3] textField] setText: _item->note];
            [[_editField[3] textField] setAutoCapsType: 1];
            [[_editField[3] textField] setPreferredKeyboardType: 0];
            break;
        case LBI_CARD:
            [_editField[0] setTitle: @"Cardname"];
            [[_editField[0] textField] setText: _item->key];
            [[_editField[0] textField] setAutoCapsType: 1];
            [[_editField[0] textField] setAutoCorrectionType: 1];
            [_editField[1] setTitle: @"Card #"];
            [[_editField[1] textField] setText: _item->value];
            [[_editField[1] textField] setAutoCapsType: 0];
            [[_editField[1] textField] setAutoCorrectionType: 4];
            [[_editField[1] textField] setPreferredKeyboardType: 1];
            [_editField[2] setTitle: @"CCV"];
            [[_editField[2] textField] setText: _item->additionalInfo];
            [[_editField[2] textField] setAutoCapsType: 0];
            [[_editField[2] textField] setPreferredKeyboardType: 1];
            [[_editField[2] textField] setAutoCorrectionType: 4];
            // TODO: Use a UIDatePicker for this instead
            [_editField[3] setTitle: @"Exp Date"];
            [[_editField[3] textField] setText: _item->expDate];
            [[_editField[3] textField] setAutoCapsType: 0];
            [[_editField[3] textField] setPreferredKeyboardType: 1];
            [_editField[4] setTitle: @"Phone"];
            [[_editField[4] textField] setText: _item->phone1];
            [[_editField[4] textField] setAutoCapsType: 0];
            [[_editField[4] textField] setPreferredKeyboardType: 2];
            [_editField[5] setTitle: @"Note"];
            [[_editField[5] textField] setText: _item->note];
            [[_editField[5] textField] setAutoCapsType: 1];
            [[_editField[5] textField] setAutoCorrectionType: 1];
            [[_editField[5] textField] setPreferredKeyboardType: 0];
            break;
        case LBI_OTHER:
            [_editField[0] setTitle: @"Description"];
            [[_editField[0] textField] setText: _item->key];
            [[_editField[0] textField] setAutoCapsType: 1];
            [[_editField[0] textField] setAutoCorrectionType: 0];
            [_editField[1] setTitle: @"Secret"];
            [[_editField[1] textField] setText: _item->value];
            [[_editField[1] textField] setAutoCapsType: 0];
            [[_editField[1] textField] setAutoCorrectionType: 1];
            [[_editField[1] textField] setPreferredKeyboardType: 0];
            [_editField[2] setTitle: @"Note"];
            [[_editField[2] textField] setText: _item->note];
            [[_editField[2] textField] setAutoCapsType: 1];
            [[_editField[2] textField] setPreferredKeyboardType: 0];
            break;
    };

    [self reconfigTags];    
    [_prefsTable reloadData];    

}

- (void)reconfigTags
{
    NSMutableString* tags = [[[NSMutableString alloc] init] autorelease];
    NSEnumerator* enumerator = [_item->tags objectEnumerator];
    NSString* tag;
    while ((tag = [enumerator nextObject])) {
        if ([tags length] > 0) [tags appendString:@", "];
        [tags appendString:tag];
    }
    [_tagsCell setValue:tags];
}

- (NSString*)getTextField:(int)fieldIdx
{
    if ([[_editField[fieldIdx] textField] text] != NULL) {
        // todo: chomp
        return [[NSString alloc] initWithString: [[_editField[fieldIdx] textField] text]];
    }
    else {
        return[[NSString alloc] init];
    }
}

- (void)save
{
    [_item deallocMembersExceptTags];

    _item->key = [self getTextField:0];
    NSLog(@"Saving key info: %@ type: %d", [[_editField[0] textField] text], _item->type);
    _item->value = [self getTextField:1];
    switch (_item->type) {
        case LBI_PASSWORD:
            _item->website = [self getTextField:2];
            _item->note = [self getTextField:3];
            break;
        case LBI_OTHER:
            _item->note = [self getTextField:2];
            break;
        case LBI_CARD:
            _item->additionalInfo = [self getTextField:2];
            _item->expDate = [self getTextField:3];
            _item->phone1 = [self getTextField:4];
            _item->note = [self getTextField:5];
            break;
    }
    //NSLog(@"website after save: %@, 0x%8x", _item->website, _item->website);
}

- (void)returnToListAndSave:(BOOL)saveOrNot
{
    if (_transDelegate != nil && [_transDelegate respondsToSelector:@selector(returnFromItemView:itemDeleted:)])
    {
        if (saveOrNot) [self save];
        [_transDelegate returnFromItemView:_item itemDeleted:!saveOrNot];
    }
}

- (void)navigationBar:(UINavigationBar*)navbar buttonClicked:(int)button
{
    NSLog(@"navBar buttonClicked: %d", button);
    switch (button) 
    {
        case 1: // Back
            [_prefsTable setKeyboardVisible:FALSE animated:TRUE];
            [self returnToListAndSave:TRUE];
            break;

        case 0: // right button
            NSLog(@"Trying keyboard type: %d", _kbType);
            [[_editField[1] textField] setPreferredKeyboardType: _kbType];
            _kbType++;
            break;
    }
}

- (void) segmentedControl: (UISegmentedControl *)segment selectedSegmentChanged: (int)seg
{
    NSLog(@"Selected segement: %i", seg);
    
    // Stop editing any rows beyond key or value as they may not be there in the next reconfig
    if ([_prefsTable editingRow] > 1) {
        /*[_prefsTable setKeyboardVisible:FALSE animated:TRUE];
        [_prefsTable _setEditingCell:NULL];
        [_prefsTable selectRow:-1 byExtendingSelection:FALSE];*/
        [_prefsTable stopEditing];        
    }
    
    if (_item) _item->type = seg;
    [self reconfig];
}

- (void)alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button
{
    [sheet dismiss];

    // Delete confirmed
    if (button == 1)
    {
        [self returnToListAndSave:FALSE];
    }    
}

// callback method called from TagView to give us the new tags upon return.
- (void)updateTags:(NSMutableArray*)newTags
{
    NSLog(@"--updateTags--");
    [_item->tags release];
    _item->tags = newTags;
    [self reconfigTags];
    [[LockboxStorage globalInstance] refreshTagCache];
}

- (BOOL)canSelectRow:(int)row
{
    // Don't allow the tags row to be selected. It's the number of type rows + 2
    NSLog(@"canSelectRow: %d");
    if (row == [self fieldCountForType] + 2) {
        NSLog(@"returning false");

        if (_transDelegate != nil && [_transDelegate respondsToSelector:@selector(transToTagView:)])
        {
            [_prefsTable stopEditing];
            [_transDelegate transToTagView:_item->tags];
        }
        return FALSE;
    }
    return TRUE;
}

- (int)fieldCountForType
{
    switch (_item->type)
    {
        case LBI_PASSWORD: 
            return 4;
        case LBI_CARD: 
            return 6;
        default: 
            return 3;
    }
}

- (void)tableRowSelected:(NSNotification *)notification
{
    // Delete clicked (it's always the last row)
    int row = [_prefsTable selectedRow];
    NSLog(@"tableRowSelected: %d editingRow %d", [_prefsTable selectedRow], [_prefsTable editingRow]);
    if (row == [_prefsTable numberOfRows] - 1)
    {
        // Delete button pressed
        UIAlertSheet *confirmSheet = [[UIAlertSheet alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
        UIPushButton *deleteButton = [confirmSheet addButtonWithTitle:@"Delete"];
        UIPushButton *cancelButton = [confirmSheet addButtonWithTitle:@"Cancel"];
        [confirmSheet setDestructiveButton:deleteButton];
        [confirmSheet setDefaultButton:cancelButton];
        [confirmSheet setDelegate:self];
        [confirmSheet setAlertSheetStyle:0];
        [confirmSheet presentSheetFromAboveView:self];
    }
    else if (row == [_prefsTable editingRow] ) {
        // user tapped the text of the field they are editing - stop editing that cell.
        [_prefsTable stopEditing];
    }
    else if (row > 0 && row <= LBIV_MAXFIELDROWS) {
        // user tapped a field different from the one they're editing. Switch focus.
        [[_editField[row - 1] textField] becomeFirstResponder];
        [_prefsTable _setEditingCell:_editField[row - 1]];
    }
    if (row == [self fieldCountForType] + 2) {
        // User tapped the tags cell
        NSLog(@"deselecting tags");
        [_tagsCell setSelected:FALSE withFade:YES];
    }

}

- (void)deleteButtonPressed:(id)sender
{
    if (_deleteDelegate && [_deleteDelegate respondsToSelector:@selector(deleteItem:)])
    {
        [_deleteDelegate deleteItem:_item];
    }
}

- (id)deleteCell
{
    if (_deleteCell == NULL) {
        NSLog(@"allocating deleteCell");
        CGRect delFrame = [_prefsTable frameOfPreferencesCellAtRow:0 inGroup:1];
        delFrame.origin.y += 15.0f;
        _deleteCell = [[UIPreferencesDeleteTableCell alloc] initWithFrame:delFrame];
        [[_deleteCell button] setTitle:@"Delete"];
        //[[_deleteCell button] addTarget:self action:@selector(deleteButtonPressed:) forEvents:255/*kGSEventTypeButtonSelected wtf is this value?*/];
    }
    return _deleteCell;
}

// Start of Preference required methods
- (int) numberOfGroupsInPreferencesTable: (UIPreferencesTable*)table 
{
    return 3;
}

- (int) preferencesTable: (UIPreferencesTable*)table numberOfRowsInGroup: (int)group 
{
    //NSLog(@"numberOfRowsInGroup: %d, type: %d", group, _item->type);
    switch (group) {
        case 0:
            if (_item == NULL) return 3;
            switch (_item->type)
            {
                case LBI_PASSWORD: 
                    return 4;
                case LBI_CARD: 
                    return 6;
                default: 
                    return 3;
            }
        case 1:
        case 2:
            return 1;
    }    
}

- (UIPreferencesTableCell*) preferencesTable: (UIPreferencesTable*)table cellForGroup: (int)group 
{
    //NSLog(@"cellForGroup: %d", group);
    if (group == 0)
        return _editCell;
    else if (group == 1) {
        return _tagGroupCell;
    }
    else if (group == 2) {
        return _delGroupCell;
    }
    else
        return NULL;
}

/*- (BOOL) preferencesTable: (UIPreferencesTable*)table isLabelGroup: (int)group 
{
    if (group == 1) return TRUE;
    return FALSE;
}*/

- (UIPreferencesTableCell*) preferencesTable: (UIPreferencesTable*)table cellForRow: (int)row inGroup: (int)group 
{
    //NSLog(@"cellForRow: %d inGroup: %d", row, group);
    if (group == 0) {
        if (row >= LBIV_MAXFIELDROWS) return NULL;
        return _editField[row];
    }
    else if (group == 1) {
        return _tagsCell;
    }
    else {
        return [self deleteCell];
    }
}

- (float) preferencesTable: (UIPreferencesTable*)table heightForRow: (int)row inGroup: (int)group withProposedHeight: (float)proposed 
{
    //NSLog(@"heightForRow: %d group: %d withProposedHeight: %4.1f", row, group, proposed);
    if (_item != NULL && group == 0) {
        // Make the Note field bigger
        /*if ((row == 3 && _item->type == LBI_PASSWORD) || (row == 2 && _item->type == LBI_KEYVALUE)) {
            CGRect bounds = [[[_editField[row] textField] _layer] bounds];
            NSLog(@"note text field bounds are %3.1f x %3.1f", bounds.size.width, bounds.size.height);
            return proposed * LBIV_NOTEFIELD_LINES;
        }*/
    }
    else if (group == 1 && row == -1) {
        return proposed * 1.6f;
    }
    return proposed;
}
// End of Preferences required modules

/*- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
 NSLog(@"LBItemView: Requested method for selector: %@", NSStringFromSelector(selector));
 return [super methodSignatureForSelector:selector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    NSLog(@"LBItemView: Request for selector: %@", NSStringFromSelector(aSelector));
    return [super respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
 NSLog(@"LBItemView: Called from: %@", NSStringFromSelector([anInvocation selector]));
[super forwardInvocation:anInvocation];
}*/

@end
